import './index.scss';
import { PropType, useTemplateRef } from 'vue';
import SvgIcon from '@/components/SvgIcon';
import { ElTooltip } from 'element-plus';

enum ISplitPanelDirection {
  Vertical = 'vertical',
  Horizontal = 'horizontal',
}

export default defineComponent({
  name: 'SplitPanel',
  props: {
    minSize: {
      type: [Number, String],
      default: 25,
    },
    size: {
      type: [Number, String],
      default: 75,
    },
    direction: {
      type: String as PropType<ISplitPanelDirection>,
      default: ISplitPanelDirection.Vertical,
    },
    resizable: {
      type: Boolean,
      default: true,
    },
    withHandler: {
      type: Boolean,
      default: true,
    },
    hideHandler: Boolean,
    hideLine: Boolean,
    hideTooltip: {
      type: Boolean,
      default: true,
    },
  },
  emits: ['resize'],
  setup(props, { emit }) {
    const minPerc = computed(() => Number(props.minSize));
    const defaultPerc = computed(() => Number(props.size));

    const isHorizontal = computed(() => props.direction === ISplitPanelDirection.Horizontal);

    const calcPerc = ref(defaultPerc.value);

    const isResizing = ref(false);

    const splitPanelContanierRef = useTemplateRef<HTMLElement>('splitPanelContanierRef');
    const defaultPanelRef = useTemplateRef<HTMLElement>('defaultPanelRef');
    const resizerRef = useTemplateRef<HTMLElement>('resizerRef');

    const resizerRect = ref<DOMRect>();
    const containerRect = ref<DOMRect>();
    const defaultPanelRect = ref<DOMRect>();

    const currentPoint = ref({ x: 0, y: 0 });

    const handleResizerMousedown = (event: MouseEvent) => {
      if (!props.resizable) return;
      isResizing.value = true;
      containerRect.value = splitPanelContanierRef.value?.getBoundingClientRect();

      currentPoint.value.x = event.clientX;
      currentPoint.value.y = event.clientY;

      defaultPanelRect.value = defaultPanelRef.value?.getBoundingClientRect();
      resizerRect.value = resizerRef.value?.getBoundingClientRect();
    };
    const handleResizerMouseup = () => {
      isResizing.value = false;
    };

    const getPercentInRange = (percent: number) => {
      if (percent < minPerc.value) return minPerc.value;
      if (percent > 100 - minPerc.value) return 100 - minPerc.value;
      return percent;
    };
    const handleResizerMousemove = (event: MouseEvent) => {
      if (isResizing.value) {
        const { clientX, clientY } = event;
        requestAnimationFrame(() => {
          if (isHorizontal.value) {
            const offsetY = currentPoint.value.y - defaultPanelRect.value!.y;
            const distanceY = currentPoint.value.y - clientY;
            const yPercent =
              ((defaultPanelRect.value!.height + distanceY - offsetY) / containerRect.value!.height) * 100;
            const newPerc = getPercentInRange(yPercent);
            calcPerc.value = newPerc;
          } else {
            const offsetX = currentPoint.value.x - defaultPanelRect.value!.x;
            const distanceX = currentPoint.value.x - clientX;
            const xPercent = ((defaultPanelRect.value!.width + distanceX - offsetX) / containerRect.value!.width) * 100;
            const newPerc = getPercentInRange(xPercent);
            calcPerc.value = newPerc;
          }
          emit('resize', calcPerc.value);
        });
      }
    };

    const handleDblClick = () => {
      if (props.resizable) {
        calcPerc.value = defaultPerc.value;
      }
    };
    return {
      splitPanelContanierRef,
      defaultPanelRef,
      isHorizontal,
      calcPerc,
      isResizing,
      handleResizerMousedown,
      handleResizerMouseup,
      handleResizerMousemove,
      handleDblClick,
    };
  },
  render() {
    const SlotPanelRender = () => {
      return (
        <div
          class="split-panel-slot"
          style={{ flexGrow: 100 - this.calcPerc, pointerEvents: this.isResizing ? 'none' : undefined }}
        >
          {this.$slots.panel?.()}
        </div>
      );
    };
    const SplitResizerRender = () => {
      return (
        this.$props.withHandler && (
          <div
            ref="resizerRef"
            class={{ 'split-panel-resizer': true, horizontal: this.isHorizontal, 'not-resizable': !this.resizable }}
            onMousedown={this.handleResizerMousedown}
            onMouseup={this.handleResizerMouseup}
            onMousemove={this.handleResizerMousemove}
            onDblclick={this.handleDblClick}
          >
            <ElTooltip
              content={this.calcPerc.toFixed(1)}
              enterable={false}
              disabled={this.hideTooltip}
              popper-class="pointer-events-none"
              placement="top"
            >
              <div class={{ 'split-panel-resizer__handler': true, hideLine: this.hideLine }}>
                {!this.hideHandler && <SvgIcon icon-class="resizer" size="12" />}
              </div>
            </ElTooltip>
          </div>
        )
      );
    };
    const DefaultPanelRender = () => {
      return (
        <div
          ref="defaultPanelRef"
          class="split-panel-default"
          style={{ flexGrow: this.calcPerc, pointerEvents: this.isResizing ? 'none' : undefined }}
        >
          {this.$slots.default?.()}
        </div>
      );
    };
    return (
      <div
        ref="splitPanelContanierRef"
        class={{ 'split-panel-container': true, horizontal: this.isHorizontal, resizing: this.isResizing }}
        onMouseup={this.handleResizerMouseup}
        onMousemove={this.handleResizerMousemove}
      >
        {SlotPanelRender()}
        {SplitResizerRender()}
        {DefaultPanelRender()}
      </div>
    );
  },
});
